home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / cpu / tms32010 / tms32010.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  28KB  |  922 lines

  1. /****************************************************************************
  2.  *                    Texas Instruments TMS320C10 DSP Emulator                *
  3.  *                                                                            *
  4.  *                        Copyright (C) 1999 by Quench                        *
  5.  *        You are not allowed to distribute this software commercially.        *
  6.  *                        Written for the MAME project.                        *
  7.  *                                                                            *
  8.  *        NOTES : The term 'DMA' within this document, is in reference        *
  9.  *                    to Direct Memory Addressing, and NOT the usual term        *
  10.  *                    of Direct Memory Access.                                *
  11.  *                This is a word based microcontroller.                        *
  12.  *                                                                            *
  13.  **************************************************************************/
  14.  
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include "driver.h"
  20. #include "cpuintrf.h"
  21. #include "mamedbg.h"
  22. #include "tms32010.h"
  23.  
  24.  
  25. #define M_RDROM(A)        TMS320C10_ROM_RDMEM(A)
  26. #define M_WRTROM(A,V)    TMS320C10_ROM_WRMEM(A,V)
  27. #define M_RDRAM(A)        TMS320C10_RAM_RDMEM(A)
  28. #define M_WRTRAM(A,V)    TMS320C10_RAM_WRMEM(A,V)
  29. #define M_RDOP(A)        TMS320C10_RDOP(A)
  30. #define M_RDOP_ARG(A)    TMS320C10_RDOP_ARG(A)
  31. #define M_IN(A)            TMS320C10_In(A)
  32. #define M_OUT(A,V)        TMS320C10_Out(A,V)
  33.  
  34. #define ADDR_MASK        TMS320C10_ADDR_MASK
  35.  
  36. #ifndef INLINE
  37. #define INLINE static inline
  38. #endif
  39. typedef struct
  40. {
  41.     UINT16    PREPC;        /* previous program counter */
  42.     UINT16  PC;
  43.     INT32   ACC, Preg;
  44.     INT32   ALU;
  45.     UINT16  Treg;
  46.     UINT16  AR[2], STACK[4], STR;
  47.     int     pending_irq, BIO_pending_irq;
  48.     int     irq_state;
  49.     int     (*irq_callback)(int irqline);
  50. } tms320c10_Regs;
  51.  
  52.  
  53. /********  The following is the Status (Flag) register definition.  *********/
  54. /* 15 | 14  |  13  | 12 | 11 | 10 | 9 |  8  | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0  */
  55. /* OV | OVM | INTM |  1 |  1 |  1 | 1 | ARP | 1 | 1 | 1 | 1 | 1 | 1 | 1 | DP */
  56. #define OV_FLAG        0x8000    /* OV    (Overflow flag) 1 indicates an overflow */
  57. #define OVM_FLAG    0x4000    /* OVM    (Overflow Mode bit) 1 forces ACC overflow to greatest positive or negative saturation value */
  58. #define INTM_FLAG    0x2000    /* INTM    (Interrupt Mask flag) 0 enables maskable interrupts */
  59. #define ARP_REG        0x0100    /* ARP    (Auxiliary Register Pointer) */
  60. #define DP_REG        0x0001    /* DP    (Data memory Pointer (bank) bit) */
  61.  
  62. static UINT8 tms320c10_reg_layout[] = {
  63.     TMS320C10_PC,TMS320C10_SP,TMS320C10_STR,TMS320C10_ACC,-1,
  64.     TMS320C10_PREG,TMS320C10_TREG,TMS320C10_AR0,TMS320C10_AR1,-1,
  65.     TMS320C10_STK0,TMS320C10_STK1,TMS320C10_STK2,TMS320C10_STK3,0
  66. };
  67.  
  68. static UINT8 tms320c10_win_layout[] = {
  69.     28, 0,52, 4,    /* register window (top rows) */
  70.      0, 0,27,22,    /* disassembler window (left colums) */
  71.     28, 5,52, 8,    /* memory #1 window (right, upper middle) */
  72.     28,14,52, 8,    /* memory #2 window (right, lower middle) */
  73.      0,23,80, 1,    /* command line window (bottom rows) */
  74. };
  75.  
  76. static UINT16   opcode=0;
  77. static UINT8    opcode_major=0, opcode_minor, opcode_minr;    /* opcode split into MSB and LSB */
  78. static tms320c10_Regs R;
  79. int tms320c10_ICount;
  80. static INT32 tmpacc;
  81. typedef void (*opcode_fn) (void);
  82.  
  83.  
  84. #define OV         ( R.STR & OV_FLAG)            /* OV    (Overflow flag) */
  85. #define OVM         ( R.STR & OVM_FLAG)        /* OVM    (Overflow Mode bit) 1 indicates an overflow */
  86. #define INTM     ( R.STR & INTM_FLAG)        /* INTM    (Interrupt enable flag) 0 enables maskable interrupts */
  87. #define ARP         ((R.STR & ARP_REG) >> 8 )    /* ARP    (Auxiliary Register Pointer) */
  88. #define DP         ((R.STR & DP_REG) << 7)    /* DP    (Data memory Pointer bit) */
  89.  
  90. #define dma         (DP | (opcode_minor & 0x07f))    /* address used in direct memory access operations */
  91. #define dmapage1 (0x80 | opcode_minor)            /* address used in direct memory access operations for sst instruction */
  92.  
  93. #define ind         (R.AR[ARP] & 0x00ff)            /* address used in indirect memory access operations */
  94. UINT16             memaccess;
  95. #define memacc     (memaccess = (opcode_minor & 0x80) ? ind : dma)
  96.  
  97.  
  98.  
  99. INLINE void CLR(UINT16 flag) { R.STR &= ~flag; R.STR |= 0x1efe; }
  100. INLINE void SET(UINT16 flag) { R.STR |=  flag; R.STR |= 0x1efe; }
  101.  
  102. INLINE void getdata(UINT8 shift,UINT8 signext)
  103. {
  104.     if (opcode_minor & 0x80) memaccess = ind;
  105.     else memaccess = dma;
  106.     R.ALU = M_RDRAM(memaccess);
  107.     if ((signext) && (R.ALU & 0x8000)) R.ALU |= 0xffff0000;
  108.     else R.ALU &= 0x0000ffff;
  109.     R.ALU <<= shift;
  110.     if (opcode_minor & 0x80) {
  111.         if ((opcode_minor & 0x20) || (opcode_minor & 0x10)) {
  112.             UINT16 tmpAR = R.AR[ARP];
  113.             if (opcode_minor & 0x20) tmpAR++ ;
  114.             if (opcode_minor & 0x10) tmpAR-- ;
  115.             R.AR[ARP] = (R.AR[ARP] & 0xfe00) | (tmpAR & 0x01ff);
  116.         }
  117.         if (~opcode_minor & 0x08) {
  118.             if (opcode_minor & 1) SET(ARP_REG);
  119.             else CLR(ARP_REG);
  120.         }
  121.     }
  122. }
  123. INLINE void getdata_lar(void)
  124. {
  125.     if (opcode_minor & 0x80) memaccess = ind;
  126.     else memaccess = dma;
  127.     R.ALU = M_RDRAM(memaccess);
  128.     if (opcode_minor & 0x80) {
  129.         if ((opcode_minor & 0x20) || (opcode_minor & 0x10)) {
  130.             if ((opcode_major & 1) != ARP) {
  131.                 UINT16 tmpAR = R.AR[ARP];
  132.                 if (opcode_minor & 0x20) tmpAR++ ;
  133.                 if (opcode_minor & 0x10) tmpAR-- ;
  134.                 R.AR[ARP] = (R.AR[ARP] & 0xfe00) | (tmpAR & 0x01ff);
  135.             }
  136.         }
  137.         if (~opcode_minor & 0x08) {
  138.             if (opcode_minor & 1) SET(ARP_REG);
  139.             else CLR(ARP_REG);
  140.         }
  141.     }
  142. }
  143.  
  144. INLINE void putdata(UINT16 data)
  145. {
  146.     if (opcode_minor & 0x80) memaccess = ind;
  147.     else memaccess = dma;
  148.     if (opcode_minor & 0x80) {
  149.         if ((opcode_minor & 0x20) || (opcode_minor & 0x10)) {
  150.             UINT16 tmpAR = R.AR[ARP];
  151.             if (opcode_minor & 0x20) tmpAR++ ;
  152.             if (opcode_minor & 0x10) tmpAR-- ;
  153.             R.AR[ARP] = (R.AR[ARP] & 0xfe00) | (tmpAR & 0x01ff);
  154.         }
  155.         if (~opcode_minor & 0x08) {
  156.             if (opcode_minor & 1) SET(ARP_REG);
  157.             else CLR(ARP_REG);
  158.         }
  159.     }
  160.     if ((opcode_major == 0x30) || (opcode_major == 0x31)) {
  161.         M_WRTRAM(memaccess,(R.AR[data])); }
  162.     else M_WRTRAM(memaccess,(data&0xffff));
  163. }
  164. INLINE void putdata_sst(UINT16 data)
  165. {
  166.     if (opcode_minor & 0x80) memaccess = ind;
  167.     else memaccess = dmapage1;
  168.     if (opcode_minor & 0x80) {
  169.         if ((opcode_minor & 0x20) || (opcode_minor & 0x10)) {
  170.             UINT16 tmpAR = R.AR[ARP];
  171.             if (opcode_minor & 0x20) tmpAR++ ;
  172.             if (opcode_minor & 0x10) tmpAR-- ;
  173.             R.AR[ARP] = (R.AR[ARP] & 0xfe00) | (tmpAR & 0x01ff);
  174.         }
  175.     }
  176.     M_WRTRAM(memaccess,(data&0xffff));
  177. }
  178.  
  179.  
  180. void M_ILLEGAL(void)
  181. {
  182.     logerror("TMS320C10:  PC = %04x,  Illegal opcode = %04x\n", (R.PC-1), opcode);
  183. }
  184.  
  185.  
  186. /* This following function is here to fill in the void for */
  187. /* the opcode call function. This function is never called. */
  188. static void other_7F_opcodes(void)  { }
  189.  
  190. static void illegal(void)    { M_ILLEGAL(); }
  191. static void abst(void)
  192.         {
  193.             if (R.ACC >= 0x80000000) {
  194.                 R.ACC = ~R.ACC;
  195.                 R.ACC++ ;
  196.                 if (OVM && (R.ACC == 0x80000000)) R.ACC-- ;
  197.             }
  198.         }
  199.  
  200. /* ** The manual does not mention overflow with the ADD? instructions *****
  201.    ** however i implelemted overflow, coz it doesnt make sense otherwise **
  202.    ** and newer generations of this type of chip supported it. I think ****
  203.    ** the manual is wrong (apart from other errors the manual has). *******
  204.  
  205. static void add_sh(void)    { getdata(opcode_major,1); R.ACC += R.ALU; }
  206. static void addh(void)        { getdata(0,0); R.ACC += (R.ALU << 16); }
  207. */
  208.  
  209. static void add_sh(void)
  210.         {
  211.             tmpacc = R.ACC;
  212.             getdata(opcode_major,1);
  213.             R.ACC += R.ALU;
  214.             if (tmpacc > R.ACC) {
  215.                 SET(OV_FLAG);
  216.                 if (OVM) R.ACC = 0x7fffffff;
  217.             }
  218.             else CLR(OV_FLAG);
  219.         }
  220. static void addh(void)
  221.         {
  222.             tmpacc = R.ACC;
  223.             getdata(0,0);
  224.             R.ACC += (R.ALU << 16);
  225.             R.ACC &= 0xffff0000;
  226.             R.ACC += (tmpacc & 0x0000ffff);
  227.             if (tmpacc > R.ACC) {
  228.                 SET(OV_FLAG);
  229.                 if (OVM) {
  230.                     R.ACC &= 0x0000ffff; R.ACC |= 0x7fff0000;
  231.                 }
  232.             }
  233.             else CLR(OV_FLAG);
  234.         }
  235. static void adds(void)
  236.         {
  237.             tmpacc = R.ACC;
  238.             getdata(0,0);
  239.             R.ACC += R.ALU;
  240.             if (tmpacc > R.ACC) {
  241.                 SET(OV_FLAG);
  242.                 if (OVM) R.ACC = 0x7fffffff;
  243.             }
  244.             else CLR(OV_FLAG);
  245.         }
  246. static void and(void)
  247.         {
  248.             getdata(0,0);
  249.             R.ACC &= R.ALU;
  250.             R.ACC &= 0x0000ffff;
  251.         }
  252. static void apac(void)
  253.         {
  254.             tmpacc = R.ACC;
  255.             R.ACC += R.Preg;
  256.             if (tmpacc > R.ACC) {
  257.                 SET(OV_FLAG);
  258.                 if (OVM) R.ACC = 0x7fffffff;
  259.             }
  260.             else CLR(OV_FLAG);
  261.         }
  262. static void br(void)        { R.PC = M_RDOP_ARG(R.PC); }
  263. static void banz(void)
  264.         {
  265.             if ((R.AR[ARP] & 0x01ff) == 0) R.PC++ ;
  266.             else R.PC = M_RDOP_ARG(R.PC);
  267.             R.ALU = R.AR[ARP]; R.ALU-- ;
  268.             R.AR[ARP] = (R.AR[ARP] & 0xfe00) | (R.ALU & 0x01ff);
  269.         }
  270. static void bgez(void)
  271.         {
  272.             if (R.ACC >= 0) R.PC = M_RDOP_ARG(R.PC);
  273.             else R.PC++ ;
  274.         }
  275. static void bgz(void)
  276.         {
  277.             if (R.ACC >  0) R.PC = M_RDOP_ARG(R.PC);
  278.             else R.PC++ ;
  279.         }
  280. static void bioz(void)
  281.         {
  282.             if (R.BIO_pending_irq) R.PC = M_RDOP_ARG(R.PC);
  283.             else R.PC++ ;
  284.         }
  285. static void blez(void)
  286.         {
  287.             if (R.ACC <= 0) R.PC = M_RDOP_ARG(R.PC);
  288.             else R.PC++ ;
  289.         }
  290. static void blz(void)
  291.         {
  292.             if (R.ACC <  0) R.PC = M_RDOP_ARG(R.PC);
  293.             else R.PC++ ;
  294.         }
  295. static void bnz(void)
  296.         {
  297.             if (R.ACC != 0) R.PC = M_RDOP_ARG(R.PC);
  298.             else R.PC++ ;
  299.         }
  300. static void bv(void)
  301.         {
  302.             if (OV) {
  303.                 R.PC = M_RDOP_ARG(R.PC);
  304.                 CLR(OV_FLAG);
  305.             }
  306.             else R.PC++ ;
  307.         }
  308. static void bz(void)
  309.         {
  310.             if (R.ACC == 0) R.PC = M_RDOP_ARG(R.PC);
  311.             else R.PC++ ;
  312.         }
  313. static void cala(void)
  314.         {
  315.             R.STACK[0] = R.STACK[1];
  316.             R.STACK[1] = R.STACK[2];
  317.             R.STACK[2] = R.STACK[3];
  318.             R.STACK[3] = R.PC & ADDR_MASK;
  319.             R.PC = R.ACC & ADDR_MASK;
  320.         }
  321. static void call(void)
  322.         {
  323.             R.PC++ ;
  324.             R.STACK[0] = R.STACK[1];
  325.             R.STACK[1] = R.STACK[2];
  326.             R.STACK[2] = R.STACK[3];
  327.             R.STACK[3] = R.PC & ADDR_MASK;
  328.             R.PC = M_RDOP_ARG((R.PC-1)) & ADDR_MASK;
  329.         }
  330. static void dint(void)        { SET(INTM_FLAG); }
  331. static void dmov(void)        { getdata(0,0); M_WRTRAM((memaccess+1),R.ALU); }
  332. static void eint(void)        { CLR(INTM_FLAG); }
  333. static void in_p(void)
  334.         {
  335.             R.ALU = M_IN((opcode_major & 7));
  336.             putdata((R.ALU & 0x0000ffff));
  337.         }
  338. static void lac_sh(void)
  339.         {
  340.             getdata((opcode_major & 0x0f),1);
  341.             R.ACC = R.ALU;
  342.         }
  343. static void lack(void)        { R.ACC = (opcode_minor & 0x000000ff); }
  344. static void lar_ar0(void)    { getdata_lar(); R.AR[0] = R.ALU; }
  345. static void lar_ar1(void)    { getdata_lar(); R.AR[1] = R.ALU; }
  346. static void lark_ar0(void)    { R.AR[0] = (opcode_minor & 0x00ff); }
  347. static void lark_ar1(void)    { R.AR[1] = (opcode_minor & 0x00ff); }
  348. static void larp_mar(void)
  349.         {
  350.             if (opcode_minor & 0x80) {
  351.                 if ((opcode_minor & 0x20) || (opcode_minor & 0x10)) {
  352.                     UINT16 tmpAR = R.AR[ARP];
  353.                     if (opcode_minor & 0x20) tmpAR++ ;
  354.                     if (opcode_minor & 0x10) tmpAR-- ;
  355.                     R.AR[ARP] = (R.AR[ARP] & 0xfe00) | (tmpAR & 0x01ff);
  356.                 }
  357.                 if (~opcode_minor & 0x08) {
  358.                     if (opcode_minor & 0x01) SET(ARP_REG) ;
  359.                     else CLR(ARP_REG);
  360.                 }
  361.             }
  362.         }
  363. static void ldp(void)
  364.         {
  365.             getdata(0,0);
  366.             if (R.ALU & 1) SET(DP_REG);
  367.             else CLR(DP_REG);
  368.         }
  369. static void ldpk(void)
  370.         {
  371.             if (opcode_minor & 1) SET(DP_REG);
  372.             else CLR(DP_REG);
  373.         }
  374. static void lst(void)
  375.         {
  376.             tmpacc = R.STR;
  377.             opcode_minor |= 0x08; /* This dont support next arp, so make sure it dont happen */
  378.             getdata(0,0);
  379.             R.STR = R.ALU;
  380.             tmpacc &= INTM_FLAG;
  381.             R.STR |= tmpacc;
  382.             R.STR |= 0x1efe;
  383.         }
  384. static void lt(void)        { getdata(0,0); R.Treg = R.ALU; }
  385. static void lta(void)
  386.         {
  387.             tmpacc = R.ACC;
  388.             getdata(0,0);
  389.             R.Treg = R.ALU;
  390.             R.ACC += R.Preg;
  391.             if (tmpacc > R.ACC) {
  392.                 SET(OV_FLAG);
  393.                 if (OVM) R.ACC = 0x7fffffff;
  394.             }
  395.             else CLR(OV_FLAG);
  396.         }
  397. static void ltd(void)
  398.         {
  399.             tmpacc = R.ACC;
  400.             getdata(0,0);
  401.             R.Treg = R.ALU;
  402.             R.ACC += R.Preg;
  403.             if (tmpacc > R.ACC) {
  404.                 SET(OV_FLAG);
  405.                 if (OVM) R.ACC = 0x7fffffff;
  406.             }
  407.             else CLR(OV_FLAG);
  408.             M_WRTRAM((memaccess+1),R.ALU);
  409.         }
  410. static void mpy(void)
  411.         {
  412.             getdata(0,0);
  413.             if ((R.ALU == 0x00008000) && (R.Treg == 0x8000))
  414.                 R.Preg = 0xc0000000;
  415.             else R.Preg = R.ALU * R.Treg;
  416.         }
  417. static void mpyk(void)
  418.         {
  419.             if (opcode & 0x1000)
  420.                 R.Preg = R.Treg * ((opcode & 0x1fff) | 0xe000);
  421.             else R.Preg = R.Treg * (opcode & 0x1fff);
  422.         }
  423. static void nop(void)        { }
  424. static void or(void)
  425.         {
  426.             getdata(0,0);
  427.             R.ALU &= 0x0000ffff;
  428.             R.ACC |= R.ALU;
  429.         }
  430. static void out_p(void)
  431.         {
  432.             getdata(0,0);
  433.             M_OUT((opcode_major & 7), (R.ALU & 0x0000ffff));
  434.         }
  435. static void pac(void)        { R.ACC = R.Preg; }
  436. static void pop(void)
  437.         {
  438.             R.ACC = R.STACK[3] & ADDR_MASK;
  439.             R.STACK[3] = R.STACK[2];
  440.             R.STACK[2] = R.STACK[1];
  441.             R.STACK[1] = R.STACK[0];
  442.         }
  443. static void push(void)
  444.         {
  445.             R.STACK[0] = R.STACK[1];
  446.             R.STACK[1] = R.STACK[2];
  447.             R.STACK[2] = R.STACK[3];
  448.             R.STACK[3] = R.ACC & ADDR_MASK;
  449.         }
  450. static void ret(void)
  451.         {
  452.             R.PC = R.STACK[3] & ADDR_MASK;
  453.             R.STACK[3] = R.STACK[2];
  454.             R.STACK[2] = R.STACK[1];
  455.             R.STACK[1] = R.STACK[0];
  456.         }
  457. static void rovm(void)        { CLR(OVM_FLAG); }
  458. static void sach_sh(void)    { putdata(((R.ACC << (opcode_major & 7)) >> 16)); }
  459. static void sacl(void)        { putdata((R.ACC & 0x0000ffff)); }
  460. static void sar_ar0(void)    { putdata(0); }
  461. static void sar_ar1(void)    { putdata(1); }
  462. static void sovm(void)        { SET(OVM_FLAG); }
  463. static void spac(void)
  464.         {
  465.             INT32 tmpPreg = R.Preg;
  466.             tmpacc = R.ACC ;
  467.             /* if (tmpPreg & 0x8000) tmpPreg |= 0xffff0000; */
  468.             R.ACC -= tmpPreg ;
  469.             if (tmpacc < R.ACC) {
  470.                 SET(OV_FLAG);
  471.                 if (OVM) R.ACC = 0x80000000;
  472.             }
  473.             else CLR(OV_FLAG);
  474.         }
  475. static void sst(void)        { putdata_sst(R.STR); }
  476. static void sub_sh(void)
  477.         {
  478.             tmpacc = R.ACC;
  479.             getdata((opcode_major & 0x0f),1);
  480.             R.ACC -= R.ALU;
  481.             if (tmpacc < R.ACC) {
  482.                 SET(OV_FLAG);
  483.                 if (OVM) R.ACC = 0x80000000;
  484.             }
  485.             else CLR(OV_FLAG);
  486.         }
  487. static void subc(void)
  488.         {
  489.             tmpacc = R.ACC;
  490.             getdata(15,0);
  491.             tmpacc -= R.ALU;
  492.             if (tmpacc < 0) {
  493.                 R.ACC <<= 1;
  494.                 SET(OV_FLAG);
  495.             }
  496.             else R.ACC = ((tmpacc << 1) + 1);
  497.         }
  498. static void subh(void)
  499.         {
  500.             tmpacc = R.ACC;
  501.             getdata(0,0);
  502.             R.ACC -= (R.ALU << 16);
  503.             R.ACC &= 0xffff0000;
  504.             R.ACC += (tmpacc & 0x0000ffff);
  505.             if ((tmpacc & 0xffff0000) < (R.ACC & 0xffff0000)) {
  506.                 SET(OV_FLAG);
  507.                 if (OVM) {
  508.                     R.ACC = (tmpacc & 0x0000ffff);
  509.                     R.ACC |= 0x80000000 ;
  510.                 }
  511.             }
  512.             else CLR(OV_FLAG);
  513.         }
  514. static void subs(void)
  515.         {
  516.             tmpacc = R.ACC;
  517.             getdata(0,0);
  518.             R.ACC -= R.ALU;
  519.             if (tmpacc < R.ACC) {
  520.                 SET(OV_FLAG);
  521.                 if (OVM) R.ACC = 0x80000000;
  522.             }
  523.             else CLR(OV_FLAG);
  524.         }
  525. static void tblr(void)
  526.         {
  527.             R.ALU = M_RDROM((R.ACC & ADDR_MASK));
  528.             putdata(R.ALU);
  529.             R.STACK[0] = R.STACK[1];
  530.         }
  531. static void tblw(void)
  532.         {
  533.             getdata(0,0);
  534.             M_WRTROM(((R.ACC & ADDR_MASK)),R.ALU);
  535.             R.STACK[0] = R.STACK[1];
  536.         }
  537. static void xor(void)
  538.         {
  539.             tmpacc = (R.ACC & 0xffff0000);
  540.             getdata(0,0);
  541.             R.ACC ^= R.ALU;
  542.             R.ACC &= 0x0000ffff;
  543.             R.ACC |= tmpacc;
  544.         }
  545. static void zac(void)        { R.ACC = 0; }
  546. static void zalh(void)        { getdata(16,0); R.ACC = R.ALU; }
  547. static void zals(void)        { getdata(0 ,0); R.ACC = R.ALU; }
  548.  
  549.  
  550. static unsigned cycles_main[256]=
  551. {
  552. /*00*/        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  553. /*10*/        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  554. /*20*/        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  555. /*30*/        1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
  556. /*40*/        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  557. /*50*/        1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
  558. /*60*/        1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1,
  559. /*70*/        1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, 1, 0,
  560. /*80*/        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  561. /*90*/        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  562. /*A0*/        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  563. /*B0*/        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  564. /*C0*/        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  565. /*D0*/        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  566. /*E0*/        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  567. /*F0*/        0, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2
  568. };
  569.  
  570. static unsigned cycles_7F_other[32]=
  571. {
  572. /*80*/        1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 1, 1,
  573. /*90*/        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1,
  574. };
  575.  
  576. static opcode_fn opcode_main[256]=
  577. {
  578. /*00*/  add_sh        ,add_sh        ,add_sh        ,add_sh        ,add_sh        ,add_sh        ,add_sh        ,add_sh
  579. /*08*/ ,add_sh        ,add_sh        ,add_sh        ,add_sh        ,add_sh        ,add_sh        ,add_sh        ,add_sh
  580. /*10*/ ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh
  581. /*18*/ ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh        ,sub_sh
  582. /*20*/ ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh
  583. /*28*/ ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh        ,lac_sh
  584. /*30*/ ,sar_ar0        ,sar_ar1    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  585. /*38*/ ,lar_ar0        ,lar_ar1    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  586. /*40*/ ,in_p        ,in_p        ,in_p        ,in_p        ,in_p        ,in_p        ,in_p        ,in_p
  587. /*48*/ ,out_p        ,out_p        ,out_p        ,out_p        ,out_p        ,out_p        ,out_p        ,out_p
  588. /*50*/ ,sacl        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  589. /*58*/ ,sach_sh        ,sach_sh    ,sach_sh    ,sach_sh    ,sach_sh    ,sach_sh    ,sach_sh    ,sach_sh
  590. /*60*/ ,addh        ,adds        ,subh        ,subs        ,subc        ,zalh        ,zals        ,tblr
  591. /*68*/ ,larp_mar    ,dmov        ,lt            ,ltd        ,lta        ,mpy        ,ldpk        ,ldp
  592. /*70*/ ,lark_ar0    ,lark_ar1    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  593. /*78*/ ,xor            ,and        ,or            ,lst        ,sst        ,tblw        ,lack        ,other_7F_opcodes
  594. /*80*/ ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk
  595. /*88*/ ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk
  596. /*90*/ ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk
  597. /*98*/ ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk        ,mpyk
  598. /*A0*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  599. /*A8*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  600. /*B0*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  601. /*B8*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  602. /*C0*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  603. /*C8*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  604. /*D0*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  605. /*D8*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  606. /*E0*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  607. /*E8*/ ,illegal        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  608. /*F0*/ ,illegal        ,illegal    ,illegal    ,illegal    ,banz        ,bv            ,bioz        ,illegal
  609. /*F8*/ ,call        ,br            ,blz        ,blez        ,bgz        ,bgez        ,bnz        ,bz
  610. };
  611.  
  612. static opcode_fn opcode_7F_other[32]=
  613. {
  614. /*80*/  nop            ,dint        ,eint        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  615. /*88*/ ,abst        ,zac        ,rovm        ,sovm        ,cala        ,ret        ,pac        ,apac
  616. /*90*/ ,spac        ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal    ,illegal
  617. /*98*/ ,illegal        ,illegal    ,illegal    ,illegal    ,push        ,pop        ,illegal    ,illegal
  618. };
  619.  
  620.  
  621.  
  622. /****************************************************************************
  623.  * Reset registers to their initial values
  624.  ****************************************************************************/
  625. void tms320c10_reset (void *param)
  626. {
  627.     R.PC  = 0;
  628.     R.STR  = 0x0fefe;
  629.     R.ACC = 0;
  630.     R.pending_irq        = TMS320C10_NOT_PENDING;
  631.     R.BIO_pending_irq    = TMS320C10_NOT_PENDING;
  632. }
  633.  
  634.  
  635. /****************************************************************************
  636.  * Shut down CPU emulation
  637.  ****************************************************************************/
  638. void tms320c10_exit (void)
  639. {
  640.     /* nothing to do ? */
  641. }
  642.  
  643.  
  644. /****************************************************************************
  645.  * Issue an interrupt if necessary
  646.  ****************************************************************************/
  647.  
  648. static int Ext_IRQ(void)
  649. {
  650.     if (INTM == 0)
  651.     {
  652.         logerror("TMS320C10:  EXT INTERRUPT\n");
  653.         SET(INTM_FLAG);
  654.         R.STACK[0] = R.STACK[1];
  655.         R.STACK[1] = R.STACK[2];
  656.         R.STACK[2] = R.STACK[3];
  657.         R.STACK[3] = R.PC & ADDR_MASK;
  658.         R.PC = 0x0002;
  659.         R.pending_irq = TMS320C10_NOT_PENDING;
  660.         return 3;  /* 3 clock cycles used due to PUSH and DINT operation ? */
  661.     }
  662.     return 0;
  663. }
  664.  
  665.  
  666.  
  667.  
  668. /****************************************************************************
  669.  * Execute IPeriod. Return 0 if emulation should be stopped
  670.  ****************************************************************************/
  671. int tms320c10_execute(int cycles)
  672. {
  673.     tms320c10_ICount = cycles;
  674.  
  675.     do
  676.     {
  677.         if (R.pending_irq & TMS320C10_PENDING)
  678.         {
  679.             int type = (*R.irq_callback)(0);
  680.             R.pending_irq |= type;
  681.         }
  682.  
  683.         if (R.pending_irq) {
  684.             /* Dont service INT if prev instruction was MPY, MPYK or EINT */
  685.             if ((opcode_major != 0x6d) || ((opcode_major & 0xe0) != 0x80) || (opcode != 0x7f82))
  686.                 tms320c10_ICount -= Ext_IRQ();
  687.         }
  688.  
  689.         R.PREPC = R.PC;
  690.  
  691.         CALL_MAME_DEBUG;
  692.  
  693.         opcode=M_RDOP(R.PC);
  694.         opcode_major = ((opcode & 0x0ff00) >> 8);
  695.         opcode_minor = (opcode & 0x0ff);
  696.  
  697.         R.PC++;
  698.         if (opcode_major != 0x07f) { /* Do all opcodes except the 7Fxx ones */
  699.             tms320c10_ICount -= cycles_main[opcode_major];
  700.             (*(opcode_main[opcode_major]))();
  701.         }
  702.         else { /* Opcode major byte 7Fxx has many opcodes in its minor byte */
  703.             opcode_minr = (opcode & 0x001f);
  704.             tms320c10_ICount -= cycles_7F_other[opcode_minr];
  705.             (*(opcode_7F_other[opcode_minr]))();
  706.         }
  707.     }
  708.     while (tms320c10_ICount>0);
  709.  
  710.     return cycles - tms320c10_ICount;
  711. }
  712.  
  713. /****************************************************************************
  714.  * Get all registers in given buffer
  715.  ****************************************************************************/
  716. unsigned tms320c10_get_context (void *dst)
  717. {
  718.     if( dst )
  719.         *(tms320c10_Regs*)dst = R;
  720.     return sizeof(tms320c10_Regs);
  721. }
  722.  
  723. /****************************************************************************
  724.  * Set all registers to given values
  725.  ****************************************************************************/
  726. void tms320c10_set_context (void *src)
  727. {
  728.     if( src )
  729.         R = *(tms320c10_Regs*)src;
  730. }
  731.  
  732. /****************************************************************************
  733.  * Return program counter
  734.  ****************************************************************************/
  735. unsigned tms320c10_get_pc (void)
  736. {
  737.     return R.PC;
  738. }
  739.  
  740.  
  741. /****************************************************************************
  742.  * Set program counter
  743.  ****************************************************************************/
  744. void tms320c10_set_pc (unsigned val)
  745. {
  746.     R.PC = val;
  747. }
  748.  
  749.  
  750. /****************************************************************************
  751.  * Return stack pointer
  752.  ****************************************************************************/
  753. unsigned tms320c10_get_sp (void)
  754. {
  755.     return R.STACK[3];
  756. }
  757.  
  758.  
  759. /****************************************************************************
  760.  * Set stack pointer
  761.  ****************************************************************************/
  762. void tms320c10_set_sp (unsigned val)
  763. {
  764.     R.STACK[3] = val;
  765. }
  766.  
  767.  
  768. /****************************************************************************
  769.  * Return a specific register
  770.  ****************************************************************************/
  771. unsigned tms320c10_get_reg(int regnum)
  772. {
  773.     switch( regnum )
  774.     {
  775.         case TMS320C10_PC: return R.PC;
  776.         /* This is actually not a stack pointer, but the stack contents */
  777.         case TMS320C10_STK3: return R.STACK[3];
  778.         case TMS320C10_ACC: return R.ACC;
  779.         case TMS320C10_STR: return R.STR;
  780.         case TMS320C10_PREG: return R.Preg;
  781.         case TMS320C10_TREG: return R.Treg;
  782.         case TMS320C10_AR0: return R.AR[0];
  783.         case TMS320C10_AR1: return R.AR[1];
  784.         default:
  785.             if( regnum <= REG_SP_CONTENTS )
  786.             {
  787.                 unsigned offset = (REG_SP_CONTENTS - regnum);
  788.                 if( offset < 4 )
  789.                     return R.STACK[offset];
  790.             }
  791.     }
  792.     return 0;
  793. }
  794.  
  795.  
  796. /****************************************************************************
  797.  * Set a specific register
  798.  ****************************************************************************/
  799. void tms320c10_set_reg(int regnum, unsigned val)
  800. {
  801.     switch( regnum )
  802.     {
  803.         case TMS320C10_PC: R.PC = val; break;
  804.         /* This is actually not a stack pointer, but the stack contents */
  805.         case TMS320C10_STK3: R.STACK[3] = val; break;
  806.         case TMS320C10_STR: R.STR = val; break;
  807.         case TMS320C10_ACC: R.ACC = val; break;
  808.         case TMS320C10_PREG: R.Preg = val; break;
  809.         case TMS320C10_TREG: R.Treg = val; break;
  810.         case TMS320C10_AR0: R.AR[0] = val; break;
  811.         case TMS320C10_AR1: R.AR[1] = val; break;
  812.         default:
  813.             if( regnum <= REG_SP_CONTENTS )
  814.             {
  815.                 unsigned offset = (REG_SP_CONTENTS - regnum);
  816.                 if( offset < 4 )
  817.                     R.STACK[offset] = val;
  818.             }
  819.     }
  820. }
  821.  
  822.  
  823. /****************************************************************************
  824.  * Set NMI line state
  825.  ****************************************************************************/
  826. void tms320c10_set_nmi_line(int state)
  827. {
  828.     /* TMS320C10 does not have a NMI line */
  829. }
  830.  
  831. /****************************************************************************
  832.  * Set IRQ line state
  833.  ****************************************************************************/
  834. void tms320c10_set_irq_line(int irqline, int state)
  835. {
  836.     if (irqline == TMS320C10_ACTIVE_INT)
  837.     {
  838.         R.irq_state = state;
  839.         if (state == CLEAR_LINE) R.pending_irq &= ~TMS320C10_PENDING;
  840.         if (state == ASSERT_LINE) R.pending_irq |= TMS320C10_PENDING;
  841.     }
  842.     if (irqline == TMS320C10_ACTIVE_BIO)
  843.     {
  844.         if (state == CLEAR_LINE) R.BIO_pending_irq &= ~TMS320C10_PENDING;
  845.         if (state == ASSERT_LINE) R.BIO_pending_irq |= TMS320C10_PENDING;
  846.     }
  847. }
  848.  
  849. void tms320c10_set_irq_callback(int (*callback)(int irqline))
  850. {
  851.     R.irq_callback = callback;
  852. }
  853.  
  854. /****************************************************************************
  855.  * Return a formatted string for a register
  856.  ****************************************************************************/
  857. const char *tms320c10_info(void *context, int regnum)
  858. {
  859.     static char buffer[16][47+1];
  860.     static int which;
  861.     tms320c10_Regs *r = context;
  862.  
  863.     which = ++which % 16;
  864.     buffer[which][0] = '\0';
  865.     if( !context )
  866.         r = &R;
  867.  
  868.     switch( regnum )
  869.     {
  870.         case CPU_INFO_REG+TMS320C10_PC: sprintf(buffer[which], "PC:%04X",  r->PC); break;
  871.         case CPU_INFO_REG+TMS320C10_SP: sprintf(buffer[which], "SP:%X", 0); /* fake stack pointer */ break;
  872.         case CPU_INFO_REG+TMS320C10_STR: sprintf(buffer[which], "STR:%04X", r->STR); break;
  873.         case CPU_INFO_REG+TMS320C10_ACC: sprintf(buffer[which], "ACC:%08X", r->ACC); break;
  874.         case CPU_INFO_REG+TMS320C10_PREG: sprintf(buffer[which], "P:%08X",   r->Preg); break;
  875.         case CPU_INFO_REG+TMS320C10_TREG: sprintf(buffer[which], "T:%04X",   r->Treg); break;
  876.         case CPU_INFO_REG+TMS320C10_AR0: sprintf(buffer[which], "AR0:%04X", r->AR[0]); break;
  877.         case CPU_INFO_REG+TMS320C10_AR1: sprintf(buffer[which], "AR1:%04X", r->AR[1]); break;
  878.         case CPU_INFO_REG+TMS320C10_STK0: sprintf(buffer[which], "STK0:%04X", r->STACK[0]); break;
  879.         case CPU_INFO_REG+TMS320C10_STK1: sprintf(buffer[which], "STK1:%04X", r->STACK[1]); break;
  880.         case CPU_INFO_REG+TMS320C10_STK2: sprintf(buffer[which], "STK2:%04X", r->STACK[2]); break;
  881.         case CPU_INFO_REG+TMS320C10_STK3: sprintf(buffer[which], "STK3:%04X", r->STACK[3]); break;
  882.         case CPU_INFO_FLAGS:
  883.             sprintf(buffer[which], "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
  884.                 r->STR & 0x8000 ? 'O':'.',
  885.                 r->STR & 0x4000 ? 'M':'.',
  886.                 r->STR & 0x2000 ? 'I':'.',
  887.                 r->STR & 0x1000 ? '.':'?',
  888.                 r->STR & 0x0800 ? 'a':'?',
  889.                 r->STR & 0x0400 ? 'r':'?',
  890.                 r->STR & 0x0200 ? 'p':'?',
  891.                 r->STR & 0x0100 ? '1':'0',
  892.                 r->STR & 0x0080 ? '.':'?',
  893.                 r->STR & 0x0040 ? '.':'?',
  894.                 r->STR & 0x0020 ? '.':'?',
  895.                 r->STR & 0x0010 ? '.':'?',
  896.                 r->STR & 0x0008 ? '.':'?',
  897.                 r->STR & 0x0004 ? 'd':'?',
  898.                 r->STR & 0x0002 ? 'p':'?',
  899.                 r->STR & 0x0001 ? '1':'0');
  900.             break;
  901.         case CPU_INFO_NAME: return "320C10";
  902.         case CPU_INFO_FAMILY: return "Texas Instruments 320C10";
  903.         case CPU_INFO_VERSION: return "1.02";
  904.         case CPU_INFO_FILE: return __FILE__;
  905.         case CPU_INFO_CREDITS: return "Copyright (C) 1999 by Quench";
  906.         case CPU_INFO_REG_LAYOUT: return (const char*)tms320c10_reg_layout;
  907.         case CPU_INFO_WIN_LAYOUT: return (const char*)tms320c10_win_layout;
  908.     }
  909.     return buffer[which];
  910. }
  911.  
  912. unsigned tms320c10_dasm(char *buffer, unsigned pc)
  913. {
  914. #ifdef MAME_DEBUG
  915.     return Dasm32010( buffer, pc );
  916. #else
  917.     sprintf( buffer, "$%04X", TMS320C10_RDOP(pc) );
  918.     return 2;
  919. #endif
  920. }
  921.  
  922.